package server;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Hashtable;

import org.json.JSONObject;

import core.Card;
import core.Constructable;
import core.FlowerGrid;
import core.Game;
import core.Location;
import core.Player;
import core.Resource;
import core.ResourceType;
import core.Road;
/**
 * The server-side Game class, handles logic
 * @author CodyS
 *
 */
public class LocalGame extends Game {
	private int counter;
	/**
	 * The index of the current player
	 */
	private int currentTurn=0;
	/**
	 * is the game playing?
	 */
	private boolean playing;
	private ArrayList<Player> unreadyPlayers = new ArrayList<Player>();
	private ArrayList<Player> readyPlayers = new ArrayList<Player>();
	private FlowerGrid myGrid;
	private Location robberLocation;
	
	public LocalGame() {
		myGrid = createNewGrid();
	}
	
	private FlowerGrid createNewGrid() {
		FlowerGrid grid = new FlowerGrid(3);
		ResourceType[] resourceArray = new ResourceType[19];
		Integer[] incomeVals = new Integer[19];
		incomeVals[0]=2;
		int j=1;
		for(int a=3;a<12;a++) {
			if(a==7) { continue; }
			incomeVals[j]=a;
			incomeVals[j+1]=a;
			j+=2;
		}
		incomeVals[18]=12;
		for(int i = 0; i < 19; i++) {
			if(i == 18) {resourceArray[i] = ResourceType.SAND; continue;}
			if(i > 14) {resourceArray[i] = ResourceType.WOOL; continue;}
			if(i > 11) {resourceArray[i] = ResourceType.ORE; continue;}
			if(i > 8) {resourceArray[i] = ResourceType.GRAIN; continue;}
			if(i > 4) {resourceArray[i] = ResourceType.BRICK; continue;}
			else resourceArray[i] = ResourceType.LUMBER;
		}
		randomize(resourceArray);
		randomize(incomeVals);
		int i=0;
		for(int x=-6;x<7;x++) {
			for(int y=-6;y<7;y++) {
				Location l = new Location(x,y);
				if(!grid.isInGrid(l)) {
					continue;
				}
				if(grid.shouldBeResource(l)) {
					grid.set(l, new Resource(myGrid,resourceArray[i],incomeVals[i]));
				}
				else {
					grid.set(l, new Constructable(grid));
				}
			}
		}
		return grid;
	}
	
	private void randomize(Object[] arr) {
		for(int i=0;i<arr.length;i++) {
			int rand = (int)Math.floor(Math.random()*arr.length);
			Object s = arr[i];
			arr[i]=arr[rand];
			arr[rand]=s;
		}
	}

	@Override
	public void addToCounter(int add) {
		counter += add;	
		turn();
	}
	public void addPlayer(Player p) {
		if(playing) {}
		else {
			unreadyPlayers.add(p);
			p.ready();
		}
	}
	@Override
	public void playerReady(Player p) {
		unreadyPlayers.remove(p);
		readyPlayers.add(p);
		if(unreadyPlayers.size()<1) {
			playing = true;
			turn();
		}
	}
	/**
	 * Start a turn, tell all the players what the counter is, then tell the current player
	 * to do their turn.
	 */
	protected void turn() {
		for(Player x : readyPlayers) {
			//x.counter(counter);
		}
		currentTurn = currentTurn % readyPlayers.size();
		readyPlayers.get(currentTurn).doTurn();
		currentTurn++;
	}
	@Override
	public void removePlayer(Player p) {
		unreadyPlayers.remove(p);
		readyPlayers.remove(p);
	}
	public JSONObject toJSON() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public void buildPoint(Constructable c, Location l) {
		myGrid.set(l, c);
	}
	public void buildRoad(Constructable c, Location l1, Location l2) {
		Road r = new Road(l1, l2, readyPlayers.get(currentTurn));
		myGrid.addRoad(r);
	}
	@Override
	public void endTurn() {
		currentTurn++;
		readyPlayers.get(currentTurn).notify();
	}
	@Override
	public void loseCards(Hashtable<ResourceType, Integer> lose) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void moveRobber(Location l) {
		robberLocation = l;
		readyPlayers.get(currentTurn).notifySteal();
	}
	@Override
	public void offerTrade(Player seeker,
			Hashtable<ResourceType, Integer> offer,
			Hashtable<ResourceType, Integer> receive) {
		for(Player p : readyPlayers) {
			p.notifyTrade(offer, receive);
		}
	}
	@Override
	public void playCard(Card c) {
		c.execute();
	}
	@Override
	public void rollDice() {
		int total = (int) (Math.random() * 6) + (int) (Math.random() * 6);
		if(total == 7)
		{
			for(int i = readyPlayers.size(); i < 5; i++)
			{
				int totalCards = readyPlayers.get(i).getTotalCards();
				if(totalCards > 7)
				{
					readyPlayers.get(i).notifyDiscard((int) (totalCards / 2));
				}
			}
			readyPlayers.get(currentTurn).notifyRobber();
		}
		else {
			Resource[] res = myGrid.getResources();
			for(Resource r : res) {
				if(r.getIncomeValue() == total) {
					r.getNeighboringConstructables();
				}
			}
		}
		
	}
	@Override
	public void steal(Player take, Player stealfrom) {
		int numberofcards = stealfrom.getTotalCards();
		if(numberofcards == 0) {return;} 
		int cardtosteal = (int) (numberofcards * Math.random());
		for(ResourceType rt : ResourceType.values()) {
			cardtosteal -= stealfrom.getResources(rt);
			if(cardtosteal <= 0) 
			{
				stealfrom.removeResoruce(rt, 1);
				take.addResource(rt, 1);
				return;
			}			
		}

	}
}
